package mis.ds.ps.ui.swing;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;

import mis.ds.ps.ui.swing.MapperTree.AVP;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Step1 extends JPanel implements ActionListener {

	private static Logger logger = Logger.getLogger(Step1.class);

	private static final long serialVersionUID = 1L;

	// Swing controls

	private JFileChooser fileChooser;
	private JComboBox cmbBDVersions, cmbMapper, cmbSheets;
	private JTextField txtFile, txtAttribute, txtValue;
	private JButton btnOpenFile, btnSaveMapper, btnNewMapper;
	private JTree treeMapper;
	private JScrollPane jScrollPane1;
	private JPanel jPanel1;
	private JLabel lblImportFile, lblPreviousDatabaseVersion, jLabel1, jLabel2, jLabel3, lblWorkingXlsSheet;
	private JCheckBox chckbxUseExistingMapper;

	private ISwingAdapter swingAdapter;
	private List<String> mapperList;
	private Map<String, Map<String, AVP>> entities;

	public Step1(ISwingAdapter sa) {

		PropertyConfigurator.configure("log4j.properties");

		// Facade
		swingAdapter = sa;

		// init controls
		initialize();
	}

	private void initialize() {

		// ===============================Previous DBVersions=======================

		lblPreviousDatabaseVersion = new JLabel("Working Database Version:");
		cmbBDVersions = new JComboBox();
		if (swingAdapter != null) {
			fillComboBox(cmbBDVersions, swingAdapter.getDBVersionsList());
		}

		cmbBDVersions.setToolTipText("Select previous version data of database");
		cmbBDVersions.setMaximumRowCount(100);
		cmbBDVersions.addActionListener(this);
		// ====================================== ==================================

		// ===============================File Chooser=======================

		lblImportFile = new JLabel("Working Import File: ");
		txtFile = new JTextField(50);
		btnOpenFile = new JButton("Open File...");
		btnOpenFile.setToolTipText("Select .xls file to import");
		fileChooser = new JFileChooser();
		btnOpenFile.addActionListener(this);
		// =============================== ==================================

		// ===============================Previous Mappers=======================
		chckbxUseExistingMapper = new JCheckBox("Use existing Mapper");
		btnNewMapper = createComponentDialogButton();
		jLabel1 = new JLabel("Working Previous Mapper: ");
		cmbMapper = new JComboBox();
		if (swingAdapter != null) {
			fillComboBox(cmbMapper, swingAdapter.getDBMapCompList());
		}
		jLabel1.setVisible(false);
		cmbMapper.setVisible(false);
		cmbMapper.addActionListener(this);
		chckbxUseExistingMapper.addActionListener(this);
		btnNewMapper.addActionListener(this);
		// ============================== =======================================

		// ===============================Entity TreeMap=======================
		jScrollPane1 = new JScrollPane();
		btnSaveMapper = new JButton("Save Mapper");
		btnSaveMapper.addActionListener(this);
		// =============================== ====================================

		// ===============================Entity AVPS=======================
		jPanel1 = new JPanel();
		jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Entity AVP"));
		jLabel2 = new JLabel("Attribute");
		jLabel3 = new JLabel("Value");
		txtAttribute = new JTextField(20);
		txtValue = new JTextField(20);
		cmbSheets = new JComboBox();
		cmbSheets.addActionListener(this);
		// =============================== ===================================

		// ===============================XLS Sheets=======================

		lblWorkingXlsSheet = new JLabel("Working XLS Sheet: ");
		// =============================== =================================

		// ========================================Design Grouping=====================================

		javax.swing.GroupLayout gl_jPanel1 = new javax.swing.GroupLayout(jPanel1);
		gl_jPanel1.setHorizontalGroup(gl_jPanel1.createParallelGroup(Alignment.LEADING).addGroup(
				gl_jPanel1
						.createSequentialGroup()
						.addGap(36)
						.addGroup(
								gl_jPanel1
										.createParallelGroup(Alignment.LEADING)
										.addGroup(
												gl_jPanel1
														.createSequentialGroup()
														.addComponent(lblWorkingXlsSheet)
														.addPreferredGap(ComponentPlacement.RELATED)
														.addComponent(cmbSheets, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
																GroupLayout.PREFERRED_SIZE))
										.addComponent(txtValue, GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE).addComponent(jLabel3)
										.addComponent(txtAttribute, GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE).addComponent(jLabel2))
						.addContainerGap()));
		gl_jPanel1.setVerticalGroup(gl_jPanel1.createParallelGroup(Alignment.LEADING).addGroup(
				gl_jPanel1
						.createSequentialGroup()
						.addContainerGap()
						.addComponent(jLabel2)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(txtAttribute, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(jLabel3)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(txtValue, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(ComponentPlacement.UNRELATED)
						.addGroup(
								gl_jPanel1.createParallelGroup(Alignment.BASELINE).addComponent(lblWorkingXlsSheet)
										.addComponent(cmbSheets, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
						.addContainerGap(20, Short.MAX_VALUE)));
		jPanel1.setLayout(gl_jPanel1);

		JTextPane txtpnColocarADescio = new JTextPane();
		txtpnColocarADescio
				.setText("Colocar a desci\u00E7\u00E3o da entidade, para que server e quais os seus atributos poss\u00EDveis para se poder acrescentar de modo din\u00E2mico");

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
		layout.setHorizontalGroup(layout
				.createParallelGroup(Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(
										layout.createParallelGroup(Alignment.LEADING)
												.addGroup(
														layout.createSequentialGroup()
																.addGroup(
																		layout.createParallelGroup(Alignment.LEADING)
																				.addGroup(
																						layout.createSequentialGroup()
																								.addGroup(
																										layout.createParallelGroup(Alignment.LEADING,
																												false)
																												.addComponent(jScrollPane1,
																														GroupLayout.PREFERRED_SIZE,
																														324,
																														GroupLayout.PREFERRED_SIZE)
																												.addComponent(chckbxUseExistingMapper)
																												.addGroup(
																														layout.createSequentialGroup()
																																.addComponent(
																																		btnNewMapper)
																																.addPreferredGap(
																																		ComponentPlacement.RELATED,
																																		GroupLayout.DEFAULT_SIZE,
																																		Short.MAX_VALUE)
																																.addComponent(
																																		btnSaveMapper)))
																								.addPreferredGap(ComponentPlacement.UNRELATED)
																								.addGroup(
																										layout.createParallelGroup(Alignment.LEADING)
																												.addComponent(jPanel1,
																														GroupLayout.PREFERRED_SIZE,
																														GroupLayout.DEFAULT_SIZE,
																														GroupLayout.PREFERRED_SIZE)
																												.addComponent(txtpnColocarADescio, 0,
																														0, Short.MAX_VALUE)))
																				.addGroup(
																						layout.createSequentialGroup()
																								.addGroup(
																										layout.createParallelGroup(Alignment.LEADING)
																												.addComponent(
																														lblPreviousDatabaseVersion)
																												.addComponent(lblImportFile))
																								.addPreferredGap(ComponentPlacement.UNRELATED)
																								.addGroup(
																										layout.createParallelGroup(Alignment.LEADING)
																												.addGroup(
																														layout.createSequentialGroup()
																																.addComponent(
																																		txtFile,
																																		GroupLayout.PREFERRED_SIZE,
																																		374,
																																		GroupLayout.PREFERRED_SIZE)
																																.addPreferredGap(
																																		ComponentPlacement.UNRELATED)
																																.addComponent(
																																		btnOpenFile,
																																		GroupLayout.PREFERRED_SIZE,
																																		118,
																																		GroupLayout.PREFERRED_SIZE))
																												.addComponent(cmbBDVersions,
																														GroupLayout.PREFERRED_SIZE,
																														GroupLayout.DEFAULT_SIZE,
																														GroupLayout.PREFERRED_SIZE))))
																.addContainerGap(53, GroupLayout.PREFERRED_SIZE))
												.addGroup(
														layout.createSequentialGroup()
																.addComponent(jLabel1)
																.addPreferredGap(ComponentPlacement.UNRELATED)
																.addComponent(cmbMapper, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
																		GroupLayout.PREFERRED_SIZE).addContainerGap(545, Short.MAX_VALUE)))));
		layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(
										layout.createParallelGroup(Alignment.BASELINE)
												.addComponent(lblPreviousDatabaseVersion)
												.addComponent(cmbBDVersions, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addPreferredGap(ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(Alignment.TRAILING)
												.addComponent(btnOpenFile)
												.addGroup(
														layout.createParallelGroup(Alignment.BASELINE)
																.addComponent(lblImportFile)
																.addComponent(txtFile, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
																		GroupLayout.PREFERRED_SIZE)))
								.addGap(34)
								.addComponent(chckbxUseExistingMapper)
								.addGap(1)
								.addGroup(
										layout.createParallelGroup(Alignment.BASELINE)
												.addComponent(jLabel1)
												.addComponent(cmbMapper, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
														GroupLayout.PREFERRED_SIZE))
								.addPreferredGap(ComponentPlacement.UNRELATED)
								.addGroup(
										layout.createParallelGroup(Alignment.LEADING, false)
												.addGroup(
														Alignment.TRAILING,
														layout.createSequentialGroup()
																.addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE,
																		Short.MAX_VALUE)
																.addGap(18)
																.addComponent(txtpnColocarADescio, GroupLayout.PREFERRED_SIZE, 122,
																		GroupLayout.PREFERRED_SIZE))
												.addComponent(jScrollPane1, Alignment.TRAILING, GroupLayout.PREFERRED_SIZE, 315,
														GroupLayout.PREFERRED_SIZE)).addPreferredGap(ComponentPlacement.UNRELATED)
								.addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(btnNewMapper).addComponent(btnSaveMapper))
								.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
		this.setLayout(layout);
		// ======================================== =========================================================
	}

	public void actionPerformed(ActionEvent e) {

		// File Chooser for file to import
		if (e.getSource() == btnOpenFile) {
			int returnval = fileChooser.showOpenDialog(Step1.this);

			if (returnval == JFileChooser.APPROVE_OPTION) {
				File file = fileChooser.getSelectedFile();
				txtFile.setText(file.getName());
				if (!swingAdapter.setImportFile(txtFile.getText())) {
					// Not valid file
					JOptionPane.showMessageDialog(this, "Extension of submitted file is not supported, please choose another file", "Invalid File",
							JOptionPane.WARNING_MESSAGE);
					txtFile.setText("");
				} else {

					String actualIndex = null;
					if (cmbSheets != null && cmbSheets.getSelectedItem() != null) {
						actualIndex = cmbSheets.getSelectedItem().toString();
					}

					if (swingAdapter != null) {
						fillComboBox(cmbSheets, swingAdapter.getSheetList());
					}

					if (actualIndex != null) {
						int index = 0;
						try {
							index = Integer.valueOf(actualIndex);
							cmbSheets.setSelectedIndex(index);
						} catch (Exception e2) {
						}
					}

				}
			}

			// Select option on version
		} else if (e.getSource() == cmbBDVersions) {

			logger.debug("User choose dbversion [" + cmbBDVersions.getSelectedItem().toString() + "]");

			// Select option on sheets
		} else if (e.getSource() == cmbSheets) {

			// String sheet = cmbSheets.getSelectedItem().toString();
			// swingAdapter.setSheet(sheet);
			// logger.debug("User choose sheet [" + sheet + "]");

			// Select an existing mapper
		} else if (e.getSource() == chckbxUseExistingMapper) {

			if (chckbxUseExistingMapper.isSelected()) {
				jLabel1.setVisible(true);
				btnNewMapper.setVisible(false);

				// Refresh mappers list
				if (swingAdapter != null) {
					fillComboBox(cmbMapper, swingAdapter.getDBMapCompList());
				}

				cmbMapper.setVisible(true);

			} else {
				jLabel1.setVisible(false);
				cmbMapper.setVisible(false);
				btnNewMapper.setVisible(true);
			}

			// Select option on comboBox
		} else if (e.getSource() == cmbMapper) {

			// Presents existing mapper option
			if (cmbMapper.getSelectedItem() != null) {

				treeMapper = new JTree();
				treeMapper.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
					public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
						treeMapperValueChanged(evt);
					}
				});
				buildMapper(cmbMapper.getSelectedItem().toString());
				jScrollPane1.setViewportView(treeMapper);
			}

			// New Mapper
		} else if (e.getSource() == btnNewMapper) {

			logger.debug("Open dialog for new mapper");
			this.add(createComponentDialogButton());

			// Select option on sheets
		}

	}

	public void buildMapper(String name) {

		// Get mapper from db
		// Override every mapperleaf of composite
		// Create a tree
		MapperTree mp = new MapperTree(swingAdapter.getCompositeMapper(name));
		entities = mp.getEntities();

		// Root node name same as mapper
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(name);

		DefaultMutableTreeNode entity, attribute;

		// Entities iterator
		Iterator<String> j = entities.keySet().iterator();
		while (j.hasNext()) {

			// entity entry
			String entityName = j.next();

			// entity name
			entity = new DefaultMutableTreeNode(entityName);
			root.add(entity);

			// map of entity attributes
			Map<String, AVP> attributes = entities.get(entityName);

			// Attributes iterator
			Iterator<String> k = attributes.keySet().iterator();
			while (k.hasNext()) {

				String attributeName = k.next();

				// attribute name + value + sheet
				attribute = new DefaultMutableTreeNode(attributeName + " " + attributes.get(attributeName));
				entity.add(attribute);
			}
		}

		DefaultTreeModel treeModel = new DefaultTreeModel(root);
		treeMapper.setModel(treeModel);
		treeMapper.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

	}

	private void treeMapperValueChanged(TreeSelectionEvent evt) {

		DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeMapper.getLastSelectedPathComponent();

		if (node == null)
			return;

		Object nodeInfo = node.getUserObject();
		if (node.isLeaf()) {

			String[] valores = nodeInfo.toString().split("-");
			txtAttribute.setText(valores[0]);

			if (valores.length > 1) {
				txtValue.setText(valores[1]);
			} else {
				txtValue.setText("");
			}

			if (txtFile.getText().equals("")) {
				cmbSheets.removeAllItems();
				cmbSheets.addItem(valores[2]);
			} else {
				cmbSheets.setSelectedIndex(Integer.parseInt(valores[2]));
			}

		}
	}

	private void fillComboBox(JComboBox cmbBox, List<String> optionList) {

		cmbBox.removeAllItems();

		if (optionList != null) {
			Iterator<String> i = optionList.iterator();
			while (i.hasNext()) {
				String item = i.next();
				cmbBox.addItem(item);

			}
		}

	}

	public JTextField getTxtFile() {
		return txtFile;
	}

	// ================================================================================================

	public JButton createComponentDialogButton() {

		Action a = new AbstractAction("New Mapper") {

			private static final long serialVersionUID = 7774539478702021339L;

			public void actionPerformed(ActionEvent e) {

				// Messages
				Object[] message = new Object[4];
				message[0] = "Composite Mapper Name";
				message[1] = new JTextField();

				// JComboBox cb = new JComboBox();
				// cb.addItem("OptionPaneDemo.component_cb1");
				// cb.addItem("OptionPaneDemo.component_cb2");
				// cb.addItem("OptionPaneDemo.component_cb3");
				// message[2] = cb;

				// message[3] = "OptionPaneDemo.componentmessage2";

				// Options
				String[] options = { "Save", "Cancel" };
				int result = JOptionPane.showOptionDialog(Step1.this, // the parent that the dialog blocks
						message, // the dialog message array
						"Create new composite mapper", // the title of the dialog window
						JOptionPane.DEFAULT_OPTION, // option type
						JOptionPane.INFORMATION_MESSAGE, // message type
						null, // optional icon, use null to use the default icon
						options, // options string array, will be made into buttons
						options[0] // option that should be made into a default button
						);
				switch (result) {
				case 0: // save

					String newMapperName = ((JTextField) message[1]).getText();
					if (newMapperName == null || newMapperName.equalsIgnoreCase("")) {
						JOptionPane.showMessageDialog(Step1.this, "Name of new composite mapper can't be null", "Invalid Mapper",
								JOptionPane.WARNING_MESSAGE);
						break;
					}

					if (!swingAdapter.createCompositeMapper(newMapperName)) {
						JOptionPane.showMessageDialog(Step1.this, "App was unable to create mapper");
						break;
					}

					JOptionPane.showMessageDialog(Step1.this, "Mapper " + newMapperName + " has been saved");

					// Refresh mappers list
					if (swingAdapter != null) {
						fillComboBox(cmbMapper, swingAdapter.getDBMapCompList());
					}

					break;
				case 1: // cancel
					JOptionPane.showMessageDialog(Step1.this, "New mapper creation canceled");
					break;
				default:
					break;
				}

			}
		};
		return createButton(a);
	}

	public JButton createButton(Action a) {
		JButton b = new JButton() {
			public Dimension getMaximumSize() {
				int width = Short.MAX_VALUE;
				int height = super.getMaximumSize().height;
				return new Dimension(width, height);
			}
		};// setting the following client property informs the button to show
			// the action text as it's name. The default is to not show the
			// action text.
		b.putClientProperty("displayActionText", Boolean.TRUE);
		b.setAction(a);
		// b.setAlignmentX(JButton.CENTER_ALIGNMENT);
		return b;
	}

}
